/**
	COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
	WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
    WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
    DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
    THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
    IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
    YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
    COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
    OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
    ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
	
	Controller. Handles hash requests of the type "#controller/method".
	@version: 1.0
	@author: nicos.giuliani@logn.ch
	Website: http://www.logn.ch	
*/

var Controller = function(app) {
	
	//Private fields
	var _this = this,
		_debug = true,
		_controllers = [],
		_app = app,
		_lang = app.lang;
	
	this.app = app;
	this.prev = false;
	this.pages = [];
	this.currentLanguage = 'en';
	
	(function(original) {

		history.pushState = function(state) {
			_this.change(state);
			return original.apply(this, arguments);
		};
	})(history.pushState);
	
	window.addEventListener("popstate", function(e) {
		_this.change(e);
	});	
	window.addEventListener("ontouchmove", function(event) {
		event.preventDefault();
	})
	
	this.buildLayout = function(layout) {

		if(!layout) {
			layout = this.app.settings.layout;
		}

		if(this.prevStyle) {
			
			var tmp = getElement('#'+this.prevStyle);
			tmp.parentNode.removeChild(tmp);
		}

		var name = 'protected/views/layout/'+layout+'/'+layout, fileref=document.createElement("link");
		fileref.setAttribute("rel", "stylesheet");
		fileref.setAttribute("type", "text/css");
		fileref.setAttribute("href", name+'.css');
		fileref.setAttribute("id", layout);
		
		this.prevStyle = layout;
		
		document.getElementsByTagName("head")[0].appendChild(fileref);
		
		return load(name+'.html').response;
	};
	
	
	this.change = function(state) {

		if (state === null) {// initial page
			this.route('#site/index');
			return;
		}
		this.route(state.srcElement.location.hash);
	};
		
	this.parse = function(token) {

		var hash, ctr, mth, args = [];
		hash = token.substr(1, token.lenght);
		hash = hash.split("/");
		
		ctr = hash[0];
		mth = hash[1];
		
		if(mth && mth.indexOf('&') != -1) {
			
			var tmp = mth.split('&');
			mth = tmp[0];
			
			for(var i = 1; i < tmp.length; i++) {
				
				if(tmp[i].indexOf('=')) {
					map = tmp[i].split('=');
					args[map[0]] = map[1];
				}
			}
		}
		
		return { controller: ctr, method: mth, args: args };
	};
	
	this.route = function(hash) {
		
		var parsed = this.parse(hash), controller = parsed.controller, method = parsed.method;

		this.controller = controller;
		this.method = method;

		if (!controller || controller == '' || controller == undefined) {
			//TODO: handle type of error nicely
			this.route('#site/index');
			return;
		}

		//If the controller has not been fetch yet
		if (!_controllers[controller]) {

			var request = load('protected/controllers/' + controller + ".js"), code;

			if (request.success) {

				code = '_controllers["' + controller + '"] = ' + request.response.compress();
				
				try {
					eval(code);
				} catch(e) {
					
					_this.loadView('compile_error', false, 'error');
					delete _controllers[controller];
					console.log(e);
					return;
				}
				
				if(_controllers[controller].layout) {
					_this.setLayout(_controllers[controller].layout);
				}
				
				// Inheritance
				_controllers[controller].prototype = this;
			} 
			if(!request.success) {
				_this.loadView('controller_not_found', false, 'error');
				return;
			}
		}
		
		/** Get arguments, check if args exist & set to the method */
		var args = parsed.args, args_str = [];
		
		/** For each method in the controller if its a function check arguments name */
		for(var i in _controllers[controller]) {

			if(_controllers[controller][i] instanceof Function) {
				
				var arg = getArgsName(_controllers[controller][i]);
				/** it is on the method*/
				if(args[arg]) {
					args_str.push(args[arg]);
				}
			}
		}
		eval('_controllers["' + controller + '"].'+method+'('+args_str.join(',')+');');
			
	};

	this.loadView = function(view, node, controller) {
		
		
		var self = this, template = this.layout, page = document.createElement('div'), id = (controller?controller:_this.controller) + '/' + view,
			w = window.innerWidth, h = window.innerHeight;
		
	
		if(this.pages[id]) {
			
			this.pages[id].removeAttribute('style');
			this.prev.setAttribute('style','display:none');
			this.prev = this.pages[id];
			document.body.innerHTML = template.replace('{content}', this.pages[id].innerHTML);
			return;
		}
		
		try {
			
			page.setAttribute('id', id);
			page.setAttribute('class', 'page');
			page.innerHTML = _this.app.language.translate(load('protected/views/' + id + '.html').response, this.currentLanguage);
	
			this.pages[id] = page;
			this.prev = page;
			
			document.body.innerHTML = template.replace('{content}', page.innerHTML);
			
		} catch(e) {
			
			console.log('Error while creating the new page. Error: '+e)
		}
	};
	
	this.redirect = function(hash) {
		window.location.hash = hash;
	};
	
	try {
		this.layout = this.buildLayout();	
		this._page_index = 0;	
	} catch(e) {
		console.log(e);
	}
};
